#include "driver.h"

osSemaphoreId_t mpu_sem = NULL;
osSemaphoreId_t bmp180_sem = NULL;

osThreadId_t lvgl_task_handle;
const osThreadAttr_t lvgl_task_attributes = {
  .name = "lvgl",
  .priority = (osPriority_t) osPriorityHigh,
  .stack_size = 512 * 4
};

osThreadId_t mpu_task_handle;
const osThreadAttr_t mpu_task_attributes = {
  .name = "mpu",
  .priority = (osPriority_t) osPriorityHigh,
  .stack_size = 512 * 2
};

osThreadId_t bmp180_task_handle;
const osThreadAttr_t bmp180_task_attributes = {
  .name = "bmp180",
  .priority = (osPriority_t) osPriorityHigh,
  .stack_size = 512 * 2
};

osThreadId_t button_task_handle;
const osThreadAttr_t button_task_attributes = {
  .name = "button",
  .priority = (osPriority_t) osPriorityHigh,
  .stack_size = 256
};


static void driver_error(uint16_t no)
{
    while(1)
    {

    }
}



void hw_mpu6050_task(void* arg)
{
    mpu_sem = osSemaphoreNew (1, 1, NULL);
    if(!mpu_sem)
    {
        driver_error(1);
    }
    while(1)
    {
        osSemaphoreAcquire(mpu_sem, osWaitForever);
        mpu6050_update();
        osSemaphoreRelease(mpu_sem);
        osDelay(10);
    }
}

void hw_bmp180_task(void* arg)
{
    bmp180_sem = osSemaphoreNew(1,1,NULL);
    while(1)
    {
        osSemaphoreAcquire(bmp180_sem, osWaitForever);
        bmp180_update();
        osSemaphoreRelease(bmp180_sem);
        osDelay(200);
    }
}

void hw_button_task(void* arg)
{
    while(1)
    {
        button_check();
        osDelay(20);
    }
}

void hw_lvgl_task(void* arg)
{
    while(1)
    {
        lv_task_handler();
        osDelay(30);
    }
}

bool get_imu_val(imu_t *val)
{
    bool ret = false;
    if(mpu_sem && val)
    {
        mpu6050_t mpu_val;
        osSemaphoreAcquire(mpu_sem, osWaitForever);
        mpu6050_read(&mpu_val);
        osSemaphoreRelease(mpu_sem);
        val->acc[0] = (float)mpu_val.acc[0] / (float)acc_sens;
        val->acc[1] = (float)mpu_val.acc[1] / (float)acc_sens;
        val->acc[2] = (float)mpu_val.acc[2] / (float)acc_sens;

        val->gryo[0] = (float)mpu_val.gryo[0] / (float)gyro_sens;
        val->gryo[1] = (float)mpu_val.gryo[1] / (float)gyro_sens;
        val->gryo[2] = (float)mpu_val.gryo[2] / (float)gyro_sens;

        val->ouler[0] = mpu_val.ouler[0];
        val->ouler[1] = mpu_val.ouler[1];
        val->ouler[2] = mpu_val.ouler[2];
        ret = true;
    }
    return ret;
}

uint32_t get_pedometer_val(void)
{
    uint32_t ret = 0;
    if(mpu_sem)
    {
        mpu6050_t mpu_val;
        osSemaphoreAcquire(mpu_sem, osWaitForever);
        mpu6050_read(&mpu_val);
        osSemaphoreRelease(mpu_sem);
        ret = mpu_val.pedometer;
    }
    return ret;
}

bool get_pressure_val(pressure_t *val)
{
    bool ret = false;

    if(bmp180_sem && val )
    {
        bmp180_val_t bmp_val;
        osSemaphoreAcquire(bmp180_sem, osWaitForever);
        bmp180_get_val(&bmp_val);
        osSemaphoreRelease(bmp180_sem);
        val->altitude = bmp_val.altitude;
        val->pressure = bmp_val.pressure;
        ret = true;
    }
    return ret;
}

float get_temperature_val(void)
{
    float ret = 0.0;

    if(bmp180_sem )
    {
        bmp180_val_t bmp_val;
        osSemaphoreAcquire(bmp180_sem, osWaitForever);
        bmp180_get_val(&bmp_val);
        osSemaphoreRelease(bmp180_sem);
        ret = bmp_val.temperature;
    }
    return ret;
}


void hw_init(void)
{
    lv_init();
    lv_port_init();
    date_time_init();
    led_init();
    battery_init();
    bmp180_init(BMP085_ULTRAHIGHRES);
    mpu6050_init();
    button_init();
}

void hw_task_init(void)
{
    lvgl_task_handle = osThreadNew(hw_lvgl_task, NULL, &lvgl_task_attributes);
    mpu_task_handle = osThreadNew(hw_mpu6050_task, NULL, &mpu_task_attributes);
    bmp180_task_handle = osThreadNew(hw_bmp180_task, NULL, &bmp180_task_attributes);
    button_task_handle = osThreadNew(hw_button_task, NULL, &button_task_handle);
}